package com.yonyou.pmclouds.plan.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.billstatus.BillStatusConst;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.businessobject.util.SortListUtil;
import com.yonyou.pmclouds.externalservice.entity.FailedExternalRecordVO;
import com.yonyou.pmclouds.externalservice.rmiitf.FailedExternalRecordQuery;
import com.yonyou.pmclouds.plan.entity.ProjectScheduleBoardVO;
import com.yonyou.pmclouds.plan.entity.ScheduleItemVO;
import com.yonyou.pmclouds.plan.entity.ScheduleVO;
import com.yonyou.pmclouds.plan.mapper.ScheduleMapper;
import com.yonyou.pmclouds.plan.rmiitf.IScheduleItemQueryService;
import com.yonyou.pmclouds.plan.rmiitf.IScheduleProgressCalculateService;
import com.yonyou.pmclouds.plan.rmiitf.IScheduleQueryService;
import com.yonyou.pmclouds.project.entity.ProjectVO;
import com.yonyou.pmclouds.project.rmiitf.ProjectSimpleQuery;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = IScheduleQueryService.class)
public class ScheduleQueryServiceImpl implements IScheduleQueryService {

    @Autowired
    private ScheduleMapper scheduleMapper;

    @Autowired
    private IScheduleItemQueryService itemQueryService;

    @Autowired
    private FailedExternalRecordQuery recordQuery;

    @Autowired
    private IScheduleProgressCalculateService progressCalculateService;

    @Autowired
    private ProjectSimpleQuery projectSimpleQuery;

    @Override
    public int queryCountByPkProject(String pkProject) throws BusinessException {
        List<ScheduleVO> scheduleVOS = scheduleMapper.queryByPkProject(pkProject);
        return scheduleVOS == null ? 0 : scheduleVOS.size();
    }

    @Override
    public ScheduleVO queryById(String pkSchedule) throws BusinessException {
        ScheduleVO scheduleVO = scheduleMapper.getById(pkSchedule);

        if (scheduleVO == null) {
            return null;
        }

        setItemVOS(new ScheduleVO[]{scheduleVO});

        return scheduleVO;
    }

    @Override
    public List<ScheduleVO> queryByPkProject(String pkProject) throws BusinessException {
        List<ScheduleVO> scheduleVOS = scheduleMapper.queryByPkProject(pkProject);

        setItemVOS(scheduleVOS.toArray(new ScheduleVO[]{}));

        return scheduleVOS;
    }

    private void setItemVOS(ScheduleVO[] scheduleVOS) throws BusinessException {
        if (scheduleVOS == null || scheduleVOS.length <= 0) {
            return;
        }

        List<String> pkScheduleList = new ArrayList<>(scheduleVOS.length);
        Set<String> pkProjectSet = new HashSet<>();

        for (ScheduleVO scheduleVO : scheduleVOS) {
            if (scheduleVO == null) {
                continue;
            }
            pkScheduleList.add(scheduleVO.getPkSchedule());
            pkProjectSet.add(scheduleVO.getPkProject());
        }

        Map<String, String> failedCommitMap = getFailedCommitInfo(pkScheduleList);

        Map<String, ProjectVO> projectVOMap = projectSimpleQuery.queryProjects(pkProjectSet.toArray(new String[]{}));

        // 获取所有的计划节点
        Map<String, List<ScheduleItemVO>> itemMap = itemQueryService.queryByPkSchedulesOnlyRoot(
                pkScheduleList.toArray(new String[]{}));
        if (itemMap == null) {
            return;
        }

        for (ScheduleVO scheduleVO : scheduleVOS) {
            // 添加提交失败的计划
            if (failedCommitMap != null && StringUtils.isNotEmpty(failedCommitMap.get(scheduleVO.getPkSchedule()))) {
                scheduleVO.setFailedCommit("[" + scheduleVO.getName() + "]计划提交失败，请重新点击提交！");
            }

            // 添加项目信息
            ProjectVO projectVO = projectVOMap.get(scheduleVO.getPkProject());
            if (projectVO != null) {
                scheduleVO.setProjectCode(projectVO.getScode());
                scheduleVO.setProjectName(projectVO.getSname());
                scheduleVO.setProjectManager(projectVO.getManager());
                scheduleVO.setIsKey(projectVO.getIskey());
                scheduleVO.setPkOrg(projectVO.getPkOrg());
                scheduleVO.setProjectState(projectVO.getProjectState());
                scheduleVO.setProjectStatusName(projectVO.getProjectStatusName());
            }

            // 添加计划任务项
            List<ScheduleItemVO> itemVOS = itemMap.get(scheduleVO.getPkSchedule());
            if (itemVOS == null || itemVOS.size() <= 0) {
                continue;
            }

            scheduleVO.setScheduleItemVOS(itemVOS.toArray(new ScheduleItemVO[]{}));

        }

        progressCalculateService.calculate(scheduleVOS, null);
    }

    private Map<String, String> getFailedCommitInfo(List<String> pkScheduleList) throws BusinessException {
        if (pkScheduleList == null || pkScheduleList.size() <= 0) {
            return null;
        }
        List<FailedExternalRecordVO> recordVOS = recordQuery.queryByPkBills(pkScheduleList);
        Map<String, String> recordVOMap = null;
        if (recordVOS != null && recordVOS.size() > 0) {
            recordVOMap = new HashMap<>();
            for (FailedExternalRecordVO recordVO : recordVOS) {
                recordVOMap.put(recordVO.getRelateKey(), recordVO.getPkFailedExternalRecord());
            }
        }

        return recordVOMap;
    }

    @Override
    public List<ScheduleVO> queryByIds(String[] pkSchedules) throws BusinessException {
        List<ScheduleVO> scheduleVOS = scheduleMapper.queryByIds(pkSchedules);

        setItemVOS(scheduleVOS.toArray(new ScheduleVO[]{}));

        return scheduleVOS;
    }

    @Override
    public List<ScheduleVO> queryByTenantId(String tenantId) throws BusinessException {
        List<ScheduleVO> scheduleVOS = scheduleMapper.queryByTenantId(tenantId);
        if (scheduleVOS == null || scheduleVOS.size() <= 0) {
            return null;
        }

        setItemVOS(scheduleVOS.toArray(new ScheduleVO[]{}));

        return scheduleVOS;
    }

    @Override
    public List<ProjectScheduleBoardVO> queryProjectScheduleBoard(String tenantId, String filterCode, String sortField, String sortWay, String orgId) throws BusinessException {
        List<ScheduleVO> scheduleVOS = this.queryByTenantId(tenantId);
        if (scheduleVOS == null || scheduleVOS.size() <= 0) {
            return new ArrayList<>();
        }

        // 将计划按项目进行组装
        List<ProjectScheduleBoardVO> scheduleBoardVOS = coverToProjectVo(scheduleVOS, filterCode, orgId);

        SortListUtil.sort(scheduleBoardVOS, sortField, sortWay);

        return scheduleBoardVOS;
    }

    /**
     * 将计划按项目进行组装
     * @param scheduleVOS 计划VO
     * @param filterCode  ongoing（进行中）、completed（已完成）、all（全部）
     * @return 项目VO
     */
    private List<ProjectScheduleBoardVO> coverToProjectVo(List<ScheduleVO> scheduleVOS, String filterCode, String orgId) throws BusinessException {
        Map<String, List<ScheduleVO>> projectIdMap = new HashMap<>();
        for (ScheduleVO scheduleVO : scheduleVOS) {
            // 将项目按组织进行过滤
            if (StringUtils.isNotEmpty(orgId) && !orgId.equalsIgnoreCase(scheduleVO.getPkOrg())) {
                continue;
            }

            List<ScheduleVO> scheduleVOSTemp = projectIdMap.get(scheduleVO.getPkProject());
            if (scheduleVOSTemp == null) {
                scheduleVOSTemp = new ArrayList<>();
                projectIdMap.put(scheduleVO.getPkProject(), scheduleVOSTemp);
            }
            scheduleVOSTemp.add(scheduleVO);
        }

        List<ProjectScheduleBoardVO> scheduleBoardVOS = new ArrayList<>(projectIdMap.size());

        for (Map.Entry<String, List<ScheduleVO>> entry : projectIdMap.entrySet()) {
            ProjectScheduleBoardVO scheduleBoardVO = new ProjectScheduleBoardVO();
            scheduleBoardVO.setPkProject(entry.getKey());

            List<ScheduleVO> scheduleVOList = entry.getValue();

            if (scheduleVOList == null || scheduleVOList.size() <= 0) {
                continue;
            }

            ScheduleVO scheduleVO = scheduleVOList.get(0);
            scheduleBoardVO.setScode(scheduleVO.getProjectCode());
            scheduleBoardVO.setSname(scheduleVO.getProjectName());
            scheduleBoardVO.setManager(scheduleVO.getProjectManager());
            scheduleBoardVO.setIsKey(scheduleVO.getIsKey());

            scheduleBoardVO.setScheduleVOList(scheduleVOList);

            scheduleBoardVOS.add(scheduleBoardVO);
        }

        // 推算项目计划时间、进度，按时完成率
        progressCalculateService.calculate(scheduleBoardVOS.toArray(new ProjectScheduleBoardVO[]{}));

        List<ProjectScheduleBoardVO> result = new ArrayList<>();
        for (ProjectScheduleBoardVO scheduleBoardVO : scheduleBoardVOS) {
            if (ProjectScheduleBoardVO.FILTER_CODE_ONGOING.equalsIgnoreCase(filterCode) && scheduleBoardVO.getProgress() != 100) {
                result.add(scheduleBoardVO);
            } else if (ProjectScheduleBoardVO.FILTER_CODE_COMPLETED.equalsIgnoreCase(filterCode) && scheduleBoardVO.getProgress() == 100) {
                result.add(scheduleBoardVO);
            } else if (ProjectScheduleBoardVO.FILTER_CODE_ALL.equalsIgnoreCase(filterCode)) {
                result.add(scheduleBoardVO);
            }
        }

        return result;
    }

    @Override
    public ScheduleVO[] queryByIdsAndProjectId(String[] projectId, String[] ids, Date startDate, Date endDate) throws BusinessException {
        ScheduleVO[] scheduleVOS = scheduleMapper.queryByIdsAndProjectId(projectId, ids, startDate, endDate);
        return scheduleVOS;
    }

    @Override
    public List<ScheduleVO> queryByProjectId(String pkProject) throws BusinessException {
        List<ScheduleVO> scheduleVOS = scheduleMapper.queryByPkProject(pkProject);
        return scheduleVOS;
    }

    @Override
    public ScheduleVO[] queryByPkOriginal(String pkOriginal) throws BusinessException {
        List<ScheduleVO> scheduleVOS = scheduleMapper.queryByPkOriginal(pkOriginal);
        List<String> schedules = new ArrayList<>();
        if(null != scheduleVOS && scheduleVOS.size() > 0){
            for(ScheduleVO scheduleVO : scheduleVOS){
                if(scheduleVO.getBillstatus() != BillStatusConst.COMMON_APPROVED_STATUS){//没有审批通过的排除
                    continue;
                }

                schedules.add(scheduleVO.getPkSchedule());
            }
            //全都没通过直接返回
            if(schedules.size() == 0){
                return new ScheduleVO[0];
            }

            List<ScheduleVO> allScheduleVOs = queryByIds(schedules.toArray(new String[]{}));

            if(null == allScheduleVOs || allScheduleVOs.size() == 0){
                return new ScheduleVO[0];
            }

            return allScheduleVOs.toArray(new ScheduleVO[]{});
        }
        return new ScheduleVO[0];
    }


    @Override
    public String findByPreId(String pkSchedule,int version) {
        version = version - 1;
        ScheduleVO scheduleVO = scheduleMapper.getById(pkSchedule);
        if(null != scheduleVO){
            ScheduleVO preScheduleVO = scheduleMapper.queryByPkOriginalAndVersion(scheduleVO.getPkOriginal(), version);
            if(null != preScheduleVO){
                return preScheduleVO.getPkSchedule();
            }
            return StringUtil.EMPTY_STRING;
        }
        return StringUtil.EMPTY_STRING;
    }

    @Override
    public Map<String, List<ScheduleVO>> queryByProjectIds(String[] projectIds) {

        List<ScheduleVO> scheduleVOS = scheduleMapper.queryByPkProjects(projectIds);

        if(scheduleVOS == null || scheduleVOS.size() == 0) return new HashMap<String, List<ScheduleVO>>();

        HashMap<String, List<ScheduleVO>> result = new HashMap<>();

        for (ScheduleVO scheduleVO : scheduleVOS) {
            List<ScheduleVO> tempSchedules = result.get(scheduleVO.getPkProject());

            if (tempSchedules == null) result.put(scheduleVO.getPkProject(),new ArrayList<ScheduleVO>());

            result.get(scheduleVO.getPkProject()).add(scheduleVO);
        }
        return result;
    }


}
